package com.thunder.ktv.scoreengine2test;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;

import com.thunder.ktv.scoreengine2sdk.ErrorCode;
import com.thunder.ktv.scoreengine2sdk.ScoreEngine2;
import com.thunder.ktv.scoreengine2test.audio.AudioRecordProvider;
import com.thunder.ktv.scoreengine2test.audio.IAudioProvider;
import com.thunder.ktv.scoreengine2test.audio.TSAudioRecordProvider;
import com.thunder.ktv.scoreengine2test.audio.WavAudioProvider;

import java.util.List;

/**
 * 打分控制类
 * 负责管理评分引擎的初始化、打分过程控制和资源释放
 */
public class ScoreController {
    private static final String TAG = "ScoreController";
    private static final int MSG_SCORE_RESULT = 1;
    private static final int MSG_ERROR = 2;
    
    private ScoreEngine2 scoreEngine;
    private ScoreEngine2.ScoreEngineConfig engineConfig;
    private volatile boolean isScoring = false;
    private volatile boolean isPaused = false;
    private Thread scoringThread;
    private final ScoreCallback callback;
    private final Object pauseLock = new Object(); // 用于暂停/恢复同步的锁对象

    // 处理打分结果的线程和Handler
    private HandlerThread resultHandlerThread;
    private Handler resultHandler;

    IAudioProvider iAudioProvider;
    /**
     * 打分结果回调接口
     */
    public interface ScoreCallback {
        // 回调增加audioFrame参数，便于UI显示波形
        void onScoreResult(ScoreEngine2.ScoreResult result, short[] audioFrame, float[] spectrum);
        void onError(String error);
    }

    interface IGetPts{
        long getPts();
    }

    IGetPts getPts = null;
    public ScoreController(ScoreCallback callback,IGetPts getPts) {
        this.callback = callback;
        this.getPts = getPts;

        initResultHandler();
        scoreEngine = new ScoreEngine2();
//        iAudioProvider = new AudioRecordProvider();
        iAudioProvider = new TSAudioRecordProvider();
//        iAudioProvider = new WavAudioProvider("/sdcard/7553043.track_vocals.wav");
//        iAudioProvider = new WavAudioProvider("/sdcard/chengdu.wav");
//        iAudioProvider = new WavAudioProvider("/sdcard/left.wav");
    }

    /**
     * 初始化结果处理线程和Handler
     */
    private void initResultHandler() {
        resultHandlerThread = new HandlerThread("ScoreResultThread");
        resultHandlerThread.start();
        
        resultHandler = new Handler(resultHandlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_SCORE_RESULT:
                        if (callback != null && msg.obj instanceof Object[]) {
                            Object[] arr = (Object[]) msg.obj;
                            callback.onScoreResult((ScoreEngine2.ScoreResult) arr[0], (short[]) arr[1],(float[]) arr[2]);
                        }
                        break;
                    case MSG_ERROR:
                        if (callback != null) {
                            callback.onError((String) msg.obj);
                        }
                        break;
                }
            }
        };
    }

    /**
     * 初始化评分引擎
     */
    public synchronized boolean initScoreEngine(byte[] baseFileData,
                                 ScoreEngine2.ScoreEngineConfig config) {
        // 初始化评分引擎
        engineConfig = config;
        boolean initSuccess = scoreEngine.initScoreEngine(
                baseFileData,
                engineConfig
        );

        if (!initSuccess) {
            String error = "初始化评分引擎失败: " + scoreEngine.getInitErrorCode().toString();
            notifyError(error);
            return false;
        }

        return true;
    }

    List<ScoreEngine2.CharEntry> getCharEntries() {
        return scoreEngine.getCharEntries();
    }

    long scoringBuffer = 0;
    long getScoringBufferTime() {
        return scoreEngine.getCurScorePtsMs();
//        return (long) ((float)scoringBuffer / (float) ScoreEngine2.SAMPLE_RATE * 1000);
    }


    int aaaa = 0;
    /**
     * 开始打分
     */
    public synchronized void startScoring() {
        if (isScoring || iAudioProvider == null) {
            return;
        }

        isScoring = true;
        isPaused = false;
        aaaa = 0;
        scoringThread = new Thread(() -> {
            short[] audioFrame = new short[ScoreEngine2.AUDIO_FRAME_SIZE];
            ScoreEngine2.ScoreResult result = new ScoreEngine2.ScoreResult();
            iAudioProvider.start();
            while (isScoring) {
                try {
                    // 控制打分频率
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
                synchronized (pauseLock) {
                    while (isPaused && isScoring) {
                        try {
                            // 当暂停时，线程等待而不是空转
                            pauseLock.wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                            return;
                        }
                    }
                    
                    if (!isScoring) {
                        break;
                    }
                    
                    // 读取音频数据
                    int readSize = iAudioProvider.read(audioFrame);
                    if (readSize <= 0) {
                        Log.d(TAG, "startScoring: read audio frame failed，readSize " + readSize);
                        continue;
                    }

                    float spectrum[] = new float[ScoreEngine2.SPECTRUM_SIZE];
                    // 打分前记录时间
                    scoringBuffer += audioFrame.length;

                    long startTime = System.currentTimeMillis();
                    long pts = -1;
                    if(getPts != null){
                        pts = getPts.getPts();
                    }
                    ErrorCode errorCode = scoreEngine.scoreAudioFrame(audioFrame, result, spectrum,pts);
                    long endTime = System.currentTimeMillis();
                    // 打印打分耗时
                    if(endTime - startTime > 20)
                        Log.d(TAG, "scoreAudioFrame耗时: " + (endTime - startTime) + " ms");
                    if (errorCode == ErrorCode.SUCCESS) {
                        if(result.isValid()){
                            aaaa++;
                            Log.d(TAG, "startScoring: " + result.overallScore + ", frameIndex " + scoreEngine.getCurFrameIndex() + ",aa " + aaaa);
                        }
                        // Log.d(TAG, "startScoring: 打分结果: "+ result);
                        // 回调时传递当前帧的PCM数据
                        notifyScoreResult(result, audioFrame.clone(),spectrum.clone());
                    } else {
                        notifyError("打分错误: " + errorCode);
                    }
                }
            }
            iAudioProvider.stop();
        });
        aaaa = 0;
        scoringThread.start();
    }
    
    /**
     * 暂停打分
     */
    public synchronized void pauseScoring() {
        isPaused = true;
        iAudioProvider.pause();
    }
    
    /**
     * 恢复打分
     */
    public synchronized void resumeScoring() {
        startScoring();
        if (!isPaused) {
            return;
        }
        isPaused = false;
        synchronized (pauseLock) {
            // 通知等待的线程继续执行
            pauseLock.notifyAll();
        }
        iAudioProvider.resume();
    }
    
    /**
     * 停止打分
     */
    public synchronized void stopScoring() {
        isScoring = false;
        // 确保暂停的线程能够退出
        synchronized (pauseLock) {
            isPaused = false;
            pauseLock.notifyAll();
        }
        
        if (scoringThread != null) {
            scoringThread.interrupt();
            try {
                scoringThread.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            scoringThread = null;
        }
    }
    
    /**
     * 释放资源
     */
    public synchronized void release() {
        stopScoring();
        if (scoreEngine != null) {
            scoreEngine.releaseScoreEngine();
            scoreEngine = null;
        }
        
        // 清理结果处理线程
        if (resultHandlerThread != null) {
            resultHandlerThread.quitSafely();
            try {
                resultHandlerThread.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            resultHandlerThread = null;
            resultHandler = null;
        }
        if(iAudioProvider != null){
            iAudioProvider.release();
            iAudioProvider = null;
        }
    }
    
    private void notifyScoreResult(final ScoreEngine2.ScoreResult result, final short[] audioFrame, float[] spectrum) {
        if (resultHandler != null) {
            // 创建结果对象的副本，避免数据竞争
            ScoreEngine2.ScoreResult resultCopy = new ScoreEngine2.ScoreResult();
            copyScoreResult(result, resultCopy);
            Message msg = resultHandler.obtainMessage(MSG_SCORE_RESULT, new Object[]{resultCopy, audioFrame,spectrum});
            resultHandler.sendMessage(msg);
        }
    }
    
    private void notifyError(final String error) {
        if (resultHandler != null) {
            Message msg = resultHandler.obtainMessage(MSG_ERROR, error);
            resultHandler.sendMessage(msg);
        }
    }
    
    /**
     * 复制打分结果对象
     */
    private void copyScoreResult(ScoreEngine2.ScoreResult src, ScoreEngine2.ScoreResult dst) {
        dst.scoreFlag = src.scoreFlag;
        dst.overallScore = src.overallScore;
        dst.pitchScore = src.pitchScore;
        dst.brightnessScore = src.brightnessScore;
        dst.rhythmScore = src.rhythmScore;
        dst.emotionScore = src.emotionScore;
        dst.breathScore = src.breathScore;
        dst.timbreScore = src.timbreScore;
        dst.totalFrames = src.totalFrames;
        
        // 复制帧特征数据
        dst.frameFeature.frameIndex = src.frameFeature.frameIndex;
        dst.frameFeature.vadValue = src.frameFeature.vadValue;
        dst.frameFeature.energy = src.frameFeature.energy;
        dst.frameFeature.pitch = src.frameFeature.pitch;
        dst.frameFeature.brightness = src.frameFeature.brightness;
        dst.frameFeature.timbre = src.frameFeature.timbre;
        // 复制基准文件帧特征数据
        dst.baseFrameFeature.frameIndex = src.baseFrameFeature.frameIndex;
        dst.baseFrameFeature.vadValue = src.baseFrameFeature.vadValue;
        dst.baseFrameFeature.energy = src.baseFrameFeature.energy;
        dst.baseFrameFeature.pitch = src.baseFrameFeature.pitch;
        dst.baseFrameFeature.brightness = src.baseFrameFeature.brightness;
        dst.baseFrameFeature.timbre = src.baseFrameFeature.timbre;
    }
} 